import { FC, useCallback, useEffect, useMemo, useState } from 'react';
import HotkeyInput from '../HotkeyInput';
import { Button, Checkbox, Form, Input, Image, message, Radio, Space, Tooltip } from 'antd';
import { IAppConfig, getConfig, setConfig } from '../../command/config';
import { ELoadingStatus } from '../../const/status';
import { open } from '@tauri-apps/plugin-dialog';
import { FolderOpenOutlined, CameraOutlined } from '@ant-design/icons';

export interface IProps {
  className?: string;
}

const ConfigForm: FC<IProps> = ({
  className,
}) => {
  const [messageApi, contextHolder] = message.useMessage();
  const [previewVisible, setPreviewVisible] = useState(false);
  const [previewUrl, setPreviewUrl] = useState('');
  const [saveLoading, setSaveLoading] = useState(ELoadingStatus.IDLE);

  const [form] = Form.useForm<IAppConfig>();
  const localHotkey = Form.useWatch('localHotkey', form);
  const remoteHotkey = Form.useWatch('remoteHotkey', form);
  const saveTypeList = Form.useWatch('saveTypeList', form);
  const remoteAddress = Form.useWatch('remoteAddress', form);

  const showSaveTypeList = useMemo(() => !!(localHotkey || remoteHotkey), [localHotkey, remoteHotkey])
  const showSavePath = useMemo(() => saveTypeList?.some(item => item === 'file' && showSaveTypeList), [saveTypeList, showSaveTypeList]);

  const fetchConfig = useCallback(() => {
    getConfig().then(res => {
      form.setFieldsValue(res);
      form.validateFields();
    });
  }, [form]);

  useEffect(() => {
    fetchConfig();
  }, [fetchConfig]);

  return (
    <Form
      form={form}
      className={className}
      layout="vertical"
      disabled={saveLoading === ELoadingStatus.LOADING}
      onFinish={(values) => {
        setSaveLoading(ELoadingStatus.LOADING);
        messageApi.open({
          key: 'save',
          type: 'loading',
          content: '保存中',
          duration: 0,
        });
        setConfig(values)
          .then(() => {
            setSaveLoading(ELoadingStatus.LOADED);
            messageApi.open({
              key: 'save',
              type: 'success',
              content: '保存成功',
              duration: 2,
            });
          })
          .catch(() => {
            setSaveLoading(ELoadingStatus.ERROR);
            messageApi.open({
              key: 'save',
              type: 'error',
              content: '保存失败',
              duration: 2,
            });
          })
          .finally(() => fetchConfig());
      }}
    >
      <Form.Item name="localHotkey" label="本地截图快捷键">
        <HotkeyInput placeholder="请依次按下键盘快捷键" />
      </Form.Item>
      <Form.Item name="localScreenTarget" label="本地截屏目标屏幕" hidden={!localHotkey}>
        <Radio.Group options={[
          { label: '主屏幕', value: 'primary' },
          { label: '所有屏幕', value: 'all' },
        ]} />
      </Form.Item>
      <Form.Item name="remoteHotkey" label="远程截图快捷键">
        <HotkeyInput placeholder="请依次按下键盘快捷键" />
      </Form.Item>
      <Form.Item
        name="remoteAddress"
        label="远程端地址"
        hidden={!remoteHotkey}
        rules={[
          { required: !!remoteHotkey, message: '请填写远程端地址' },
          {
            validator: (_, value) => {
              try {
                if (!remoteHotkey || !value) {
                  return Promise.resolve();
                }
                new URL(value);
                return Promise.resolve();
              } catch (err) {
                return Promise.reject('无效的 URL');
              }
            }
          }
        ]}>
        <Input
          placeholder="如: http://127.0.0.1:8520/screenshot?screen=primary&format=jpg"
          allowClear
          suffix={
            <Tooltip title="测试从远程获取截图">
              <Button
                type="text"
                size="small"
                icon={<CameraOutlined />}
                onClick={() => {
                  form.validateFields(['remoteAddress']).then(() => {
                    const url = new URL(remoteAddress!);
                    url.searchParams.append('randomTestId', Math.random().toString());
                    setPreviewUrl(url.toString());
                    setPreviewVisible(true);
                  }).catch(() => {
                    messageApi.error('请正确填写远程端地址');
                  });
                }}
              />
            </Tooltip>
          }
        />
      </Form.Item>
      <Form.Item
        name="saveTypeList"
        label="截图保存方式"
        hidden={!showSaveTypeList}
        rules={[{ required: showSaveTypeList, message: '至少选择一种截图保存方式' }]}>
        <Checkbox.Group options={[
          { label: '剪切板', value: 'clipboard' },
          { label: '文件', value: 'file' },
        ]} />
      </Form.Item>
      <Form.Item
        name="imgSaveType"
        label="图片存储格式"
        hidden={!showSavePath}>
        <Radio.Group options={[
          { label: 'JPG', value: 'jpg' },
          { label: 'PNG', value: 'png' },
        ]} />
      </Form.Item>
      <Form.Item
        name="savePath"
        label="截图文件保存路径"
        hidden={!showSavePath}
        rules={[{ required: showSavePath, message: '请输入截图保存文件夹路径' }]}>
        <Input
          placeholder="请输入截图保存文件夹路径"
          allowClear
          suffix={
            <Tooltip title="选择文件夹">
              <Button
                type="text"
                size="small"
                icon={<FolderOpenOutlined />}
                onClick={() => {
                  open({
                    multiple: false,
                    directory: true,
                    title: '请选择截图保存文件夹',
                  }).then(res => {
                    if (res) {
                      form.setFieldValue('savePath', res);
                    }
                  });
                }}
              />
            </Tooltip>
          } />
      </Form.Item>
      <Form.Item
        name="autoCreateSavePath"
        label="目录不存在时自动创建"
        valuePropName="checked"
        hidden={!showSavePath}
      >
        <Checkbox>自动创建目录</Checkbox>
      </Form.Item>
      <Form.Item>
        <Space>
          <Button type="primary" htmlType="submit">保存</Button>
          <Button onClick={fetchConfig}>重置</Button>
        </Space>
      </Form.Item>

      <Image
        hidden
        preview={{
          visible: previewVisible,
          imageRender: () => (
            <img
              src={previewUrl}
              onError={() => {
                messageApi.error('远程截图测试失败');
              }}
              onLoad={() => {
                messageApi.success('远程截图测试成功');
              }}
              style={{ height: '95%', width: '95%', objectFit: 'contain' }}
            />
          ),
          onVisibleChange: (value) => {
            setPreviewVisible(value);
          },
          toolbarRender: () => null,
        }}
      />
      {contextHolder}
    </Form>
  );
}

export default ConfigForm;